#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

//       int semget(key_t key, int nsems, int semflg);
//       key_t ftok(const char *pathname, int proj_id);
//       int semop(int semid, struct sembuf *sops, size_t nsops);
//       int semctl(int semid, int semnum, int cmd, ...);

union semun {
               int              val;    /* Value for SETVAL */
               struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
               unsigned short  *array;  /* Array for GETALL, SETALL */
               struct seminfo  *__buf;  /* Buffer for IPC_INFO
                                           (Linux-specific) */
           };

void Init_sem(int semid,int value){

	union semun tmp;
	tmp.val = value;
	if((semctl(semid,0,SETVAL,tmp)) == -1){
		
		perror("Init sem error");
		exit(-1);		
	}
}

int Del_sem(int semid){
	
	union semun tmp;
	if((semctl(semid,0,IPC_RMID,tmp)) == -1){
	
		perror("Del sem error");
		exit(-1);		
	}
}

void v_sem(int semid){

	struct sembuf sbuf;

	sbuf.sem_num = 0;        /* Operate on semaphore 0 */
        sbuf.sem_op = 1;         /* Wait for value to equal 0 */
        sbuf.sem_flg = SEM_UNDO;
	if(semop(semid,&sbuf,1) == -1){
		
		perror("V error why");
		exit(-1);
	}
}


void p_sem(int semid){

	struct sembuf sbuf;

	sbuf.sem_num = 0;        /* Operate on semaphore 0 */
        sbuf.sem_op = -1;         /* Wait for value to equal 0 */
        sbuf.sem_flg = SEM_UNDO;
	if(semop(semid,&sbuf,1) == -1){
		
		perror("P error why");
		exit(-1);
	}
}

int main(){

	key_t key;
	int semid;
	pid_t pid;

	if((key = ftok(".",'m')) < 0){
		
		perror("ftok error");
		exit(-1);
	}

	if((semid = semget(key,1,IPC_CREAT|0666)) == -1){
		
		perror("segmet error");
		exit(-1);
	}

	Init_sem(semid,0);

	pid = fork();

	if(pid == 0){
	
		printf("This is child pid= %d\n",getpid());
		sleep(2);
		v_sem(semid);
	}
	else if(pid > 0){
		
		p_sem(semid);
		printf("This is father pid= %d\n",getpid());
		v_sem(semid);
		Del_sem(semid);
	}
	else{
		perror("fork error");
		exit(-1);
	}

	return 0;
}
